<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="../index.css">
  <link rel="stylesheet" href="../common.css">
  <title>Title</title>
</head>
<body>
  <div class="container">
    <div class="page-content">
      <div class="content-box">
        <div class="content-title">职责链模式</div>
        <div class="content-intr-txt">一系列可能会处理请求的对象被连成一条链，请求在这些对象之间一次传递，直到遇到一个可以处理它的对象，我们把这个对象成为链中的节点。</div>
        <div class="content-intr-txt">例如：电商网站对支付定金的用户有一些优惠活动，支付500元定金可优惠100元，支付200元定金可优惠50元，没有支付定金的只能普通的购买方式，且没有优惠，并且库存有限不一定保证购买。</div>
        <div class="example-txt">实现一个order函数，它接受三个参数orderType，pay，stock</div>
        <ul class="intr-list">
          <li class="list-item-intr">orderType: 表示订单类型，1表示500元定金，2表示200定金，3表示普通用户</li>
          <li class="list-item-intr">pay: 是否支付定金，true false</li>
          <li class="list-item-intr">stock: 表示普通用户与未支付定金用户能购买的总库存量</li>
        </ul>
        <pre style="text-align: left;">
          // 正常不是职责链模式的代码编写
          <code>
            var order = function(orderType, pay, stock) {
              if (orderType === 1) {
                if (pay === true) {
                  console.log('500元定金预约，优惠100元')
                } else {
                  if (stock > 0) {
                    console.log('普通购买，无优惠券')
                  } else {
                    console.log('库存不足')
                  }
                }
              } else if (orderType === 2) {
                if (pay === true) {
                  console.log('200元定金预约，优惠50元')
                } else {
                  if (stock > 0) {
                    console.log('普通购买，无优惠券')
                  } else {
                    console.log('库存不足')
                  }
                }
              } else {
                if (stock > 0) {
                  console.log('普通购买，无优惠券')
                } else {
                  console.log('库存不足')
                }
              }
            }
            order(1, true, 500);
          </code>
          // 代码可以看出来，运行结构没问题，代码量大，不好阅读，难以维护
        </pre>
      </div>
      <div class="content-box">
        <div class="content-intr-txt">使用职责链模式来重构代码：将500，200定金与没有支付定金分别独立成函数， 代码如下：</div>
        <pre>
          // 使用职责链模式优化2
          <code>
            var order500 = function(orderType, pay, stock) {
              if (orderType === 1 && pay === true) {
                console.log('500元定金预约，优惠100元')
              } else {
                order200(orderType, pay, stock)
              }
            }

            var order200 = function(orderType, pay, stock) {
              if (orderType === 2 && pay === true) {
                console.log('200元定金预约，优惠50元')
              } else {
                orderNormal(orderType, pay, stock);
              }
            }

            var orderNormal = function(orderType, pay, stock) {
              if (stock > 0) {
                console.log('普通购买，无优惠券')
              } else {
                console.log('手机库存不足！')
              }
            }

            order500(1, true, 30);
            order500(1, false, 30);
            order500(2, true, 30);
            order500(2, false, 30);
            order500(3, true, 0);
          </code>
          // 这里使用职责链模式对代码进行 分离的优化，是的原来的order函数被优化为三个小的函数各司其责
          // 但是这里还是存在很大问题，职责链顺序被强硬的耦合在一起，不能方便的调整
        </pre>
      </div>
      <div class="content-box">
        <div class="content-intr-txt">优化职责链模式：灵活可拆分的职责链节点</div>
        <div class="content-intr-txt">将三种不同模式的购买方式拆分为上述的三个函数节点，如果某个节点不能处理则返回一个约定的字段'next'继续向下执行</div>
      </div>
    </div>
  </div>
  <script>
    (function(){
      // 正常不是职责链模式的代码编写
      /*var order = function(orderType, pay, stock) {
        if (orderType === 1) {
          if (pay === true) {
            console.log('500元定金预约，优惠100元')
          } else {
            if (stock > 0) {
              console.log('普通购买，无优惠券')
            } else {
              console.log('库存不足')
            }
          }
        } else if (orderType === 2) {
          if (pay === true) {
            console.log('200元定金预约，优惠50元')
          } else {
            if (stock > 0) {
              console.log('普通购买，无优惠券')
            } else {
              console.log('库存不足')
            }
          }
        } else {
          if (stock > 0) {
            console.log('普通购买，无优惠券')
          } else {
            console.log('库存不足')
          }
        }
      }

      order(1, true, 500);
      // 代码可以看出来，运行结构没问题，代码量大，不好阅读，难以维护*/

      // 使用职责链模式优化2
      /*var order500 = function(orderType, pay, stock) {
        if (orderType === 1 && pay === true) {
          console.log('500元定金预约，优惠100元')
        } else {
          order200(orderType, pay, stock)
        }
      }

      var order200 = function(orderType, pay, stock) {
        if (orderType === 2 && pay === true) {
          console.log('200元定金预约，优惠50元')
        } else {
          orderNormal(orderType, pay, stock);
        }
      }

      var orderNormal = function(orderType, pay, stock) {
        if (stock > 0) {
          console.log('普通购买，无优惠券')
        } else {
          console.log('手机库存不足！')
        }
      }

      order500(1, true, 30);
      order500(1, false, 30);
      order500(2, true, 30);
      order500(2, false, 30);
      order500(3, true, 0);
      // 这里使用职责链模式对代码进行 分离的优化，是的原来的order函数被优化为三个小的函数各司其责
      // 但是这里还是存在很大问题，职责链顺序被强硬的耦合在一起，不能方便的调整*/

      // 使用职责链模式优化3
      var optimizeOrder500 = function(orderType, pay, stock) {
        if (orderType === 1 && pay === true) {
          console.log('500元定金预约，优惠100元')
        } else {
          return 'next';
        }
      }

      var optimizeOrder200 = function(orderType, pay, stock) {
        if (orderType === 2 && pay === true) {
          console.log('200元定金预约，优惠50元')
        } else {
          return 'next';
        }
      }

      var optimizeOrder300 = function(orderType, pay, stock) {
        if (orderType === 3 && pay === true) {
          console.log('300元定金预约，优惠120元')
        } else {
          return 'next';
        }
      }

      var orderNormal = function(orderType, pay, stock) {
        if (stock) {
          console.log('普通购买，无优惠券');
        } else {
          console.log('手机库存不足！')
        }
      }

      var Chain = function(fn) {
        this.fn = fn;
        this.successor = null;
      }

      Chain.prototype.setNextSuccessor = function(successor) {
        return this.successor = successor;
      }

      Chain.prototype.passRequest = function() {
        var ret = this.fn.apply(this, arguments);

        if (ret === 'next') {
          return this.successor && this.successor.passRequest.apply(this.successor, arguments)
        }

        return ret;
      }

      var chainOrder500 = new Chain(optimizeOrder500);
      var chainOrder300 = new Chain(optimizeOrder300);
      var chainOrder200 = new Chain(optimizeOrder200);
      var chainOrderNormal = new Chain(orderNormal);

      chainOrder500.setNextSuccessor(chainOrder300);
      chainOrder300.setNextSuccessor(chainOrder200);
      chainOrder200.setNextSuccessor(chainOrderNormal);

      chainOrder500.passRequest(1, true, 10)
      chainOrder500.passRequest(1, false, 10)
      chainOrder500.passRequest(2, true, 10)
      chainOrder500.passRequest(2, false, 10)
      chainOrder500.passRequest(3, true, 10)
      chainOrder500.passRequest(3, false, 10)
      chainOrder500.passRequest(4, true, 0 )
    })()
  </script>
</body>
</html>